home *** CD-ROM | disk | FTP | other *** search
/ PCMania 30 / PCMania CD30.iso / sharewar / graphic / sprmaker / cargar.doc < prev    next >
Text File  |  1994-12-29  |  17KB  |  471 lines

  1.  
  2.  
  3.  
  4.  
  5.      ¿ Como hacer un programa utilizando sprites?
  6.  
  7.  
  8.  
  9.  
  10.      Este texto pretende explicar como hacer programas
  11. utilizando sprites, en el lenguaje Turbo Pascal, espero que
  12. los programadores de Turbo C no tengan demasiados problemas a
  13. la hora de adaptar las rutinas.
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.      Prácticamente todos los juegos que existen en el mercado
  26. están programados utilizando los modos gráficos de la vga, mas
  27. concretamente el modo 320 x 200 x 256, pues bien, el primer
  28. problema que nos encontramos a la hora de programar un juego,
  29. o una utilidad con un entorno gráfico es la manera de activar
  30. este modo, con los lenguajes de Borland podemos encontrar los
  31. drivers que nos activaran los modos gráficos requeridos en
  32. multitud de programas, pero no ( hasta la fecha ) los modos de
  33. 256 colores en vga o Svga, gracias al shareware se pueden
  34. encontrar en el mercado unos drivers pensados para esto, yo en
  35. concreto voy a utilizar el driver SVGA256.BGI de Jordan
  36. Hargrave ( Hi, Jordan :-)), para registraros a este driver tan
  37. solo tendréis que pagarle 20$ al autor, si bien también
  38. podréis optar por otra opción, que seria activar la vga en ASM
  39. o Ensamblador, esto es bien fácil con la interrupción 10h de
  40. la bios, de esta forma MOV AX,0013h , INT 10h ya tendríamos la
  41. vga 320x200x256 activada, pero no podremos contar con toda la
  42. librería de gráficos que se nos  suministra con el compilador,
  43. aunque al programar todas las rutinas gráficas en ASM
  44. tendremos algo de mas rapidez.
  45.  
  46.  
  47.      Pues bien, para activar la vga con el driver SVGA.BGI lo
  48. primero que tendremos que hacer es decirle al compilador que
  49. este driver no es de los que el lleva incorporado, si no que
  50. es un driver de usuario ajeno al compilador, esto lo haremos
  51. con el comando -> InstallUserDriver tal que así:
  52. Driver:=InstallUserDriver('SVGA256',NIL); y luego
  53. inicializando el modo con: Initgraph(Driver,graphmode,'');
  54. donde graphmode puede ser un numero del 0 al 6 que representan
  55. todos los modos de svga, de esta forma activaremos la svga
  56. cargando el driver svga256.bgi del disco, pero existe una
  57. forma mas profesional de hacer esto, que es incluir el driver
  58. en tu mismo programa como un objeto, evitando que el driver
  59. este en un fichero independiente, y tiempo de acceso al disco
  60. dándole mas rapidez al programa a la hora de cargarse, esto lo
  61. podemos conseguir convirtiendo el driver SVGA256.BGI a obj con
  62. el comando que se incluye con vuestro compilador BINOBJ de
  63. esta forma BINOBJ SVGA256.BGI SVGA256 SVGA256, ya tenemos el
  64. driver como objeto, después solo nos queda añadir esta línea
  65. en nuestro programa:
  66.  PROCEDURE SVGA256;EXTERNAL
  67.  {$L SVGA256.OBJ}
  68. Y ya le tendremos en nuestro programa, para que todo os quede
  69. mas claro os incluyo la unit que programe para Sprite Maker.
  70.  
  71.  
  72. UNIT SVGA;
  73.  
  74. INTERFACE
  75. const
  76.   XNOR_PUT              = 5;
  77.   NOR_PUT               = 6;
  78.   NAND_PUT              = 7;
  79.   TRANS_COPY_PUT        = 8;
  80.  
  81.  
  82. PROCEDURE SVGA256;
  83. PROCEDURE INICIA(GRAPHMODE:INTEGER);
  84. IMPLEMENTATION
  85. USES GRAPH;
  86.  
  87. VAR GRAPHDRIVER:INTEGER;
  88.  
  89. PROCEDURE SVGA256;EXTERNAL;
  90. {$L SVGA256.OBJ}
  91. PROCEDURE INICIA;
  92. BEGIN
  93. GRAPHDRIVER:=INSTALLUSERDRIVER('SVGA256',nil);
  94. IF REGISTERBGIDRIVER(@SVGA256)<0 THEN HALT(1);
  95. initgraph(graphdriver,graphmode,'');
  96. END;
  97. END.
  98.  
  99.  
  100.     Para usarla tan solo tendreis que incluirla en la linea de units del
  101. programa principal, y llamar al procedimiento inicia en el momento que
  102. deseis activar el modo grafico: INICIA(0) activara el modo 320x200x256.
  103.     Graphmode puede tomar estos valores:
  104.  
  105.  0=320x200x256 VGA/MCGA
  106.  1=640x400x256   SVGA
  107.  2=640x480x256   SVGA
  108.  3=800x600x256   SVGA
  109.  4=1024x768x256  SVGA
  110.  5=640x350x256   SVGA
  111.  6=1280x1024x256 SVGA
  112.  
  113.     Bueno, ya por fin podemos dedicarnos a los sprites ;-)
  114. una vez que hemos activado los modos gráficos de la vga la
  115. cosa es mas fácil, por lo menos en Turbo Pascal ya que podemos
  116. usar todos los comandos de la unit graph, pero siempre queda
  117. la opción de que nos programemos algunas rutinas en ASM para
  118. darle mas rapidez al programa.
  119.  
  120.  
  121.      Lo primero que tenemos que saber de los sprites es como
  122. cargarlos, o como incluirlos dentro del programa, para todo
  123. esto son muy importantes los punteros sin tipo, que se
  124. declaran como SPRITE:POINTER, ellos nos servirán para saber en
  125. que posición de la memoria tenemos el dibujo que hay que
  126. llevar a la memoria de pantalla, pero esto que suena un tanto
  127. complicado no lo es, ahora lo veréis.
  128.  
  129.      Para cargar un sprite utilizaremos el comando Blockread:
  130.  
  131.  
  132.     ·BlockRead, procedimiento·
  133.  
  134. Lee e introduce uno o más registros en una variable.
  135.  
  136.  Declaración:
  137.  procedure BlockRead(var F: File; var Buf; Count: Word [; var Result:
  138.     Word]);
  139. donde:
  140.    F        variable tipo fichero sin tipo
  141.    Buf      cualquier variable
  142.    Count    una expresión de tipo Word
  143.    Result   una variable de tipo Word
  144.  
  145.  Target:
  146. Windows, Real, Protected
  147.  
  148.  Observaciones:
  149. F es una variable de tipo fichero sin tipo, Buf es cualquier variable, Count
  150. es una expresiónde tipo Word, y Result es una variable de tipo Word.
  151.  
  152. BlockRead lee Count o menos registros del fichero F a la memoria, empezando
  153. en el primer byte ocupado por Buf. El número verdadero de registros
  154. completos leídos (menor o igual que Count) se devuelve en el parámetro
  155. opcional Result. Si Result no se especifica, se produce un error E/S si el
  156. número leído no es igual que Count.
  157.  
  158. El bloque transferido completo ocupa como mucho Count symbol * RecSize
  159. bytes, siendo RecSize el tamaño de registro especificado cuando el fichero
  160. fue abierto (o 128 si el tamaño de registro no se especificó). Se produce
  161. error si Count symbol * RecSize es mayor que 65,535 (64K).
  162.  
  163. Result es un parámetro opcional. Si fue transferido el bloque completo,
  164. Result será igual a Count. Si no, si Result es menor que Count, el final del
  165. fichero fue alcanzado antes de que se completara la transferencia. En ese
  166. caso, si el tamaño de registro del fichero es mayor que 1, Result devuelve
  167. el númerode registros completos leídos.
  168.  
  169. La posición de fichero actual es adelantada Result registros a causa de
  170. BlockRead.
  171.  
  172. Con {$I-}, IOResult devuelve 0 si la operación fue satisfactoria; si no,
  173. devuelve un código de error distinto de cero.
  174.  
  175.  Restricciones:
  176. El fichero debe estar abierto.
  177.  
  178.  
  179.      El fichero primero tendremos que abrirlo con reset y
  180. luego cargar todos los bytes que ocupa en una variable
  181. dinámica con la ayuda de un puntero.
  182.  
  183.      F1:='NOMBRE.SPR'; Le damos el nombre una variable string
  184.  
  185.      ASSIGN(F,F1); asignamos este nombre a una variable
  186.            fichero
  187.      RESET(F,1); abrimos el fichero indicando que la lectura
  188.          será de un byte en un byte.
  189.      SIZE:=FILESIZE(F); obtenemos el tamaño del fichero
  190.  
  191.      GETMEN(SPRITE,SIZE); y con el creamos una variable
  192.              dinámica utilizando el puntero
  193.              sprite.
  194.      BLOCKREAD(F,SPRITE^,SIZE,SIZE); y cargamos todo el dibujo
  195.                      a esta variable.
  196.      CLOSE(F);
  197.  
  198.      No os olvidéis de que para un correcto uso de la memoria
  199. toda las variables dinámicas que dejen de ser útiles tendréis
  200. que liberarlas o mejor dicho liberar esta memoria con freemen.
  201.  
  202.         Ya lo tenemos en memoria, solo nos queda mostrarlo en
  203. pantalla, para eso utilizaremos el comando PUTIMAGE, pero
  204. antes vamos a ver como se puede incluir los sprites en el
  205. mismo programa, creando un solo fichero ejecutable que
  206. contenga todos los gráficos. Para esto os será muy útil el
  207. apartado anterior de como incluir el driver SVGA256.BGI en tu
  208. mismo programa, ya que el procedimiento es el mismo.
  209.  
  210.      Ejemp: el sprite casa.spr lo queremos incluir en nuestro
  211. programa, lo primero es convertirlo a objeto, así:
  212. BINOBJ CASA.SPR CASA CASA
  213.      Ya esta, ahora le añadimos a nuestro programa la
  214. siguiente línea.
  215. PROCEDURE CASA;EXTERNAL;
  216. {$L CASA.OBJ}
  217.  
  218.      Y le asignamos un puntero:
  219. SPRITE:=@CASA;
  220.      Ya esta listo para el siguiente paso, el de mostrarlo en
  221. pantalla, como veis todos los sprites los utilizo con punteros
  222. que indican la posición en memoria del dibujo, esto es lo mas
  223. practico, porque un solo puntero puede servirnos para muchos
  224. sprites, pero también podemos usar un array con el tamaño del
  225. sprite en cuestión, ya que el comando putimage lo que necesita
  226. es simplemente una variable que contenga el dibujo. Aquí
  227. tenéis el comando PUTIMAGE y GETIMAGE:
  228.  
  229.     ·PutImage, procedimiento     (Graph unit)·
  230.  
  231. Sitúa una imágen binaria en la pantalla.
  232.  
  233.  Declaración:
  234.  procedure PutImage(X, Y: Integer; var BitMap; BitBlt: Word);
  235.  
  236.  Target:
  237. Real, Protected
  238.  
  239.  Observaciones:
  240. (X, Y) es la esquina superior izquierda de una región rectangular en la
  241. pantalla. BitMap es un parámetro sin tipo que contiene la altura y la
  242. anchura de la región, y la imágen binaria que será puesta en la pantalla.
  243. BitBlt especifica que operador binario será usado para situar la imágen
  244. binaria en la pantalla.
  245.  
  246. Cada constante corresponde a una operación binaria. Por ejemplo:
  247.  
  248. PutImage(X, Y, BitMap, NormalPut) pone la imágen almacenada en BitMap en (X,
  249. Y) usando la instrucción de lenguaje de ensamblador MOV para cada byte en la
  250. imágen.
  251.  
  252. PutImage(X, Y, BitMap, XORPut) pone la imágen almacenada en BitMap en (X, Y)
  253. usando la instrucción de lenguaje de ensamblador XOR para cada byte en la
  254. imágen. Esta es una técnica de animación usada a menudo para "arrastrar" una
  255. imágen por la pantalla.
  256.  
  257. PutImage(X, Y, BitMap, NotPut) invierte los bits en BitMap y entonces pone
  258. la imágen almacenada en BitMap en (X, Y) usando el lenguaje de ensamblador
  259. MOV en la imágen. Así, la imágen aparece en vídeo inverso del BitMap
  260. original.
  261.  
  262.  Restricciones:
  263. Debe usarse en modo gráfico.
  264.  
  265.  
  266.  
  267.  
  268.  
  269.     ·GetImage, procedimiento     (Graph unit)·
  270.  
  271. Grava una imagen binaria de la región especificada en un buffer.
  272.  
  273.  Declaración:
  274.  procedure GetImage(x1, y1, x2, y2: Integer; var BitMap);
  275.  
  276.  Target:
  277. Real, Protected
  278.  
  279.  Observaciones:
  280. X1, Y1, X2, y Y2 definen una región rectangular en la pantalla. BitMap es un
  281. parámetro sin tipo que debe ser mayor o igual que 6 la cantidad de área
  282. definida por la región. Las dos primeras palabras de BitMap almacenan la
  283. altura y la anchura de la región. La tercera palabra está reservada.
  284.  
  285. El resto de BitMap se usa para grabar la imágen binaria en sí. Usar la
  286. función ImageSize para determinar los requerimientos de tamaño de BitMap.
  287.  
  288.  Restricciones:
  289. Debe usarse en modo gráfico. la memoria necesaria para grabar la región debe
  290. ser menos que 64K.
  291.  
  292.  
  293.  
  294.      Así que para ver los sprites que anteriormente hemos
  295. cargado solo tendremos que hacer:
  296.  
  297. PUTIMAGE(120,50,SPRITE^,NORMALPUT);
  298.      Y para leer una porción de un dibujo en pantalla:
  299. GETIMAGEN(120,50,140,80,FONDO^);
  300.      Siendo fondo otro puntero.
  301.  
  302.      Así el mover por la pantalla un sprite es bastante fácil:
  303.      x,y:word;
  304.  
  305.  
  306. x:=10;
  307. y:=20;
  308. getimage(x,y,x+20,y+20,fondo^);
  309. putimage(x,y,sprite^,trans_copy_put);
  310. for x:=10 to 300 do
  311.      begin
  312.      putimage(x,y,fondo^,normalput);
  313.      getimage(x+1,y,x+21,y+20,fondo^);
  314.      putimage(x+1,y,sprite^,trans_copy_put);
  315.      end;
  316.  
  317. Si queréis que el movimiento sea mas rápido, tan solo tendréis
  318. que decirle que de saltos de 2 o 4 en 4.
  319.  
  320.  
  321.  
  322.      Para los que se decidan a programar en ASM os diré que el
  323. sprite esta formado por:
  324.  
  325.      4 bytes que representan:
  326.      Los primeros 2 un word o palabra que indica la longitud
  327.      del eje X.
  328.      Los siguientes 2 son el otro word que indica la longitud
  329.      del eje Y.
  330.  
  331.      Todos los siguientes bytes son el dibujo, cada pixel es
  332. un byte, ya que estamos trabajando con sprites de 256 colores
  333. 2^8, los X primeros bytes del dibujo corresponderán a este
  334. eje, y se repetirán en número de Y.
  335.  
  336.      Estos sprites pueden ser usados en cualquier modo de la
  337. SVGA con 256 colores, a mayor resolución menor será el sprite.
  338.  
  339.  
  340.  
  341.            ¿Como cambio los colores?
  342.  
  343.  
  344.      Bien, llegados a este punto nos encontramos con que
  345. podemos cargar sprites en nuestro programa, moverlos, etc,
  346. pero tenemos un problema, los sprites no se ven con los mismos
  347. colores que tenían en el programa Sprite Maker, eso es debido
  348. a que el programa carga la paleta de colores para cada sprite,
  349. pero vuestro programa no, y muestra los sprites con los
  350. colores que tenía la vga en el momento de activarla, entonces
  351. lo que tendremos que hacer será cargar la paleta original de
  352. los sprites. Pero antes será mejor que aprendamos algo mas
  353. sobre como trabaja la vga con estos colores.
  354.  
  355.  
  356.  
  357.  
  358.      Cuando nosotros activamos un punto la pantalla con algún
  359. modo de la SVGA 256C, estamos escribiendo en la memoria de
  360. pantalla un byte, osea 8 bits que pueden tener 2^8
  361. convinaciones, lo que es 256 convinaciones, generalmente
  362. solemos decir que este es el color, pero no es del todo
  363. exacto, es el Nº de color en pantalla que en este modo solo
  364. puede ser de 256C pero tenemos 262.144 colores para elegir,
  365. esta es la paleta. Para cada uno de los 256 colores que podemos
  366. tener en pantalla tenemos 18bits repartidos en 6 bits por
  367. color básico ( Rojo,Verde,Azul), de esta forma por cada color
  368. básico tenemos 2^6=64 grados de intensidad con lo que al
  369. convinar los tres colores con los 18 bits tendremos
  370. 2^18=262.144 colores, si por cada uno de los 256 colores que
  371. podemos tener en pantalla tenemos 3 bytes de los cuales solo
  372. se utilizan los primeros 6 bits (0-5) entonces tendremos
  373. 3*256=768 bytes para la tabla de colores de este modo, esta es
  374. la tabla de tonalidades del DAC ( Digital to Analog Converter)
  375. los circuitos que convierten la señal digital de nuestro
  376. ordenador (1bit= 0=0v,1=5v TTL) en analógica ( escalas de
  377. tensión donde 1 byte o mas, como los 18bits se puede
  378. representar por una sola línea en escalas de V) para que
  379. podamos ver ese punto en nuestro monitor. Pues son esos 768
  380. bytes los que tendremos que cambiar para poder ver los colores
  381. originales de los sprites.
  382.  
  383.  
  384.  
  385.      Los colores originales de los sprites los podemos
  386. encontrar en los ficheros *.PAL que crea el programa Sprite
  387. Maker al salvar la paleta.
  388.  
  389.  
  390.      Para cargarlos como siempre podemos optar por dos formas,
  391. la primera seria cargando el fichero *.pal desde el disco por
  392. vuestro programa utilizando el comando BLOCKREAD, exactamente
  393. igual que con los sprites, y la segunda seria incluir la
  394. paleta en nuestro programa convirtiéndola en un obj, no os voy
  395. a explicar este proceso, porque es igual que lo ya explicado,
  396. y como siempre tendremos que usar un puntero asociado a la
  397. paleta, lo que si os voy a explicar es como llevar esta paleta
  398. dentro de la tabla del DAC.
  399.  
  400.  
  401.  
  402.  
  403.      Para cargar la paleta en los registros del DAC vamos a
  404. usar la interrupción 10 función 10 subfunción 12 para cargar
  405. varios registros de color del DAC.
  406.  
  407.      Las entradas en los registros del mp son:
  408.      AH=10h       Que corresponde a la función.
  409.      AL=12H       La subfunción.
  410.      BX=   Número del primer registro de color direccionado    
  411.        (0-255).
  412.      CX=   Cantidad de registros a cargar.
  413.      ES=   Dirección de segmento del Buffer.
  414.      Dx=   Dirección de offset(o desplazamiento dentro del
  415.        segmento ) del Buffer.
  416.  
  417.  
  418.  
  419.      Para cargar toda la paleta seria:
  420.  
  421. REG.AX:=$1012;
  422. REG.BX:=$00;
  423. REG.CX:=$100;
  424. REG.ES:=SEG(PALETA); -> SEGMENTO 
  425. REG.DX:=OFS(PALETA); -> DESPLAZAMIENTO DENTRO DEL SEGMENTO.
  426. INTR($10,REG);
  427.  
  428.      Donde PALETA es un puntero que apunta al buffer, buffer
  429. es la memoria donde esta los 768 bytes de la paleta, segmento
  430. es el dato alto de la dirección del buffer, offset el dato
  431. bajo de la dirección del buffer.
  432.  
  433.  
  434.      Para las personas que esten empezando con la programacion les
  435. aconsejo que revisen los libros de ( Referencia al programador, Guia del
  436. usuario, Guia del lenguaje ) que vienen con su compilador de Turbo Pascal,
  437. prestar atención sobre todo en los temas relacionados con punteros.
  438.  
  439.     Un libro que tambien os sera muy util es: PC INTERNO de Michael
  440. Tischer, Data Becker edicion, Marcombo Boixareu editores.
  441.  
  442.  
  443.  
  444.      Turbo Pascal y Turbo C son marcas registradas de Borland
  445. International, Inc.
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.            Para mas Información:
  455.  
  456.  
  457.  
  458.            Enrique Sanchez Martinez
  459.            Apartado Nº 71 Barrio Issac Peral
  460.            CP:30300 Cartagena España (SPAIN)
  461.  
  462.      O EN
  463.  
  464. --------------> BBS CLUB
  465.         2 LINEAS 14.400
  466.         CD ROM
  467.         (968) 201819
  468.         (968) 201262
  469.  
  470.  
  471.